package com.blacktech.dbu.meta.controller;

import com.blacktech.dbu.core.controller.BaseCrudController;
import com.blacktech.dbu.core.dto.SearchRequest;
import com.blacktech.dbu.core.response.PageResponse;
import com.blacktech.dbu.core.response.ResponseCode;
import com.blacktech.dbu.core.exception.BusinessException;
import com.blacktech.dbu.meta.entity.DbuSchema;
import com.blacktech.dbu.meta.repository.SchemaRepository;
import com.blacktech.dbu.meta.service.SchemaService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 数据库模式管理Controller
 * 提供数据库模式的完整CRUD操作和搜索功能
 *
 * @author Yanyunsong
 */
@RestController
@RequestMapping("/api/schemas")
@Tag(name = "数据库模式管理", description = "数据库模式信息的增删改查和搜索")
public class SchemaController extends BaseCrudController<DbuSchema, Long> {

    private final SchemaRepository schemaRepository;
    private final SchemaService schemaService;

    @Autowired
    public SchemaController(SchemaRepository schemaRepository, SchemaService schemaService) {
        this.schemaRepository = schemaRepository;
        this.schemaService = schemaService;
    }

    @Override
    protected DbuSchema doCreate(DbuSchema entity) {
        return schemaService.createSchema(entity);
    }

    @Override
    protected DbuSchema doGetById(Long id) {
        return schemaRepository.findById(id).orElse(null);
    }

    @Override
    protected Page<DbuSchema> doGetAll(Pageable pageable) {
        return schemaRepository.findAll(pageable);
    }

    @Override
    protected List<DbuSchema> doGetAllWithoutPagination() {
        return schemaRepository.findAll();
    }

    @Override
    protected DbuSchema doUpdate(Long id, DbuSchema entity) {
        return schemaService.updateSchema(id, entity);
    }

    @Override
    protected boolean doDelete(Long id) {
        if (!schemaRepository.existsById(id)) {
            return false;
        }
        schemaRepository.deleteById(id);
        return true;
    }

    @Override
    protected int doBatchDelete(List<Long> ids) {
        return schemaService.batchDeleteSchemas(ids);
    }

    @Override
    protected Page<DbuSchema> doSearch(Specification<DbuSchema> specification, Pageable pageable) {
        return schemaRepository.findAll(specification, pageable);
    }

    @Override
    protected Class<DbuSchema> getEntityClass() {
        return DbuSchema.class;
    }

    @Override
    protected Predicate addCustomSearchConditions(
            SearchRequest searchRequest,
            Root<DbuSchema> root,
            CriteriaQuery<?> query,
            CriteriaBuilder criteriaBuilder) {

        // 添加关联字段的特殊处理
        if (searchRequest.getExactMatches() != null) {
            Object productId = searchRequest.getExactMatches().get("productId");
            if (productId != null && productId instanceof String) {
                return criteriaBuilder.equal(root.get("product").get("id"), Long.valueOf((String) productId));
            }
        }

        return null;
    }

    /**
     * 根据产品ID获取所有数据库模式
     */
    @GetMapping("/product/{productId}")
    @Operation(summary = "根据产品ID获取数据库模式", description = "获取指定产品下的所有数据库模式，按名称排序")
    public List<DbuSchema> getSchemasByProductId(
            @Parameter(description = "产品ID") @PathVariable Long productId) {
        return schemaRepository.findByProductIdOrderBySchemaName(productId);
    }

    /**
     * 检查产品下Schema名称是否存在
     */
    @GetMapping("/check-exists")
    @Operation(summary = "检查Schema名称是否存在", description = "检查指定产品下的Schema名称是否已被使用")
    public Boolean checkSchemaExists(
            @Parameter(description = "产品ID") @RequestParam Long productId,
            @Parameter(description = "Schema名称") @RequestParam String schemaName) {
        return schemaRepository.existsByProductIdAndSchemaName(productId, schemaName);
    }

    /**
     * 检查Schema名称是否存在（排除指定ID）
     */
    @GetMapping("/check-exists/exclude/{id}")
    @Operation(summary = "检查Schema名称是否存在（排除指定ID）", description = "检查指定产品下的Schema名称是否已被使用，排除指定Schema ID")
    public Boolean checkSchemaExistsExclude(
            @Parameter(description = "产品ID") @RequestParam Long productId,
            @Parameter(description = "Schema名称") @RequestParam String schemaName,
            @Parameter(description = "排除的Schema ID") @PathVariable Long id) {
        return schemaRepository.existsByProductIdAndSchemaNameAndIdNot(productId, schemaName, id);
    }

    /**
     * 根据产品ID和Schema名称查找Schema
     */
    @GetMapping("/product/{productId}/name/{schemaName}")
    @Operation(summary = "根据产品和Schema名称查找", description = "通过产品ID和Schema名称精确查找Schema")
    public DbuSchema getSchemaByProductIdAndName(
            @Parameter(description = "产品ID") @PathVariable Long productId,
            @Parameter(description = "Schema名称") @PathVariable String schemaName) {
        DbuSchema schema = schemaRepository.findByProductIdAndSchemaName(productId, schemaName);
        if (schema == null) {
            throw new BusinessException(ResponseCode.NOT_FOUND.getCode(), "Schema不存在");
        }
        return schema;
    }

    /**
     * 根据产品ID列表查找Schema
     */
    @PostMapping("/by-products")
    @Operation(summary = "根据产品ID列表查找Schema", description = "根据产品ID列表查找相关的Schema，按产品和Schema名称排序")
    public List<DbuSchema> getSchemasByProductIds(
            @Parameter(description = "产品ID列表") @RequestBody List<Long> productIds) {
        return schemaRepository.findByProductIdInOrderByProductNameAscSchemaNameAsc(productIds);
    }

    /**
     * 获取Schema统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取Schema统计信息", description = "获取Schema的数量统计和按数据库类型分布")
    public Object getSchemaStatistics() {
        long totalSchemas = schemaRepository.count();

        // 按数据库类型统计
        var typeStats = schemaRepository.getSchemaTypeStatistics();

        return java.util.Map.of(
                "totalSchemas", totalSchemas,
                "typeDistribution", typeStats
        );
    }
}